package com.binguo.wxapi.baidu;

import com.binguo.common.util.FileUtil;
import com.binguo.common.util.ImageBase64Util;
import com.binguo.common.util.JsonUtil;
import com.binguo.model.mapper.BranchMapper;
import com.binguo.model.mapper.ShopBaiduUrlCurMapper;
import com.binguo.model.mapper.ShopBaiduUrlMapper;
import com.binguo.model.model.Branch;
import com.binguo.model.model.ShopBaiduUrl;
import com.binguo.model.model.ShopBaiduUrlCur;
import com.binguo.wxapi.baidu.model.BaiduRecResult;
import com.binguo.youtu.sign.Base64Util;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.entity.Condition;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class BaiduRecUtil {
    private static Logger logger = LoggerFactory.getLogger(BaiduRecUtil.class);

    private static String appid = "16805085";
    private static String apiKey = "3t7PQUPeThDcPyEpUNh8UHZA";
    private static String securityKey = "SciYNqyHOip2GnS5jDjw5nCgeaqFA85w";

    public static String tokenKey = "baiduToken";
    private static String baiduAppidKey = "baiduAppid";
    private static Long tokenExpireTime = 0l;

    @Resource
    private ShopBaiduUrlMapper shopBaiduUrlMapper;
    @Resource
    private ShopBaiduUrlCurMapper shopBaiduUrlCurMapper;
    @Resource
    private BranchMapper branchMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    public static String tokenKeyCur = "baiduTokenCur";
    private static String baiduAppidKeyCur = "baiduAppidCur";


    public void setKey(String key, String value, long time){
        redisTemplate.opsForValue().set(key, value, time, TimeUnit.MILLISECONDS);
    }


    public Object getKey(String key){
        return redisTemplate.opsForValue().get(key);
    }



    public String getBaiduTokenCur(Integer shopId, Integer branchId) {
        Object tokenObj = getKey(tokenKeyCur + shopId + branchId);

        if (tokenObj == null) {
            Condition condition = new Condition(ShopBaiduUrlCur.class);
            condition.or().andEqualTo("shopId", shopId);
            List<ShopBaiduUrlCur> shopBaiduUrlList = shopBaiduUrlCurMapper.selectByCondition(condition);
            if (shopBaiduUrlList != null && shopBaiduUrlList.size() > 0) {
                ShopBaiduUrlCur recObj = null;

                if (branchId != null) {
                    for (ShopBaiduUrlCur temp : shopBaiduUrlList) {
                        if (temp.getUrlType() != null && temp.getUrlType().intValue() == 2
                                && branchId.equals(temp.getBranchId())
                                ) {
                            recObj = temp;
                            break;
                        }
                    }
                }else {
                    for (ShopBaiduUrlCur temp : shopBaiduUrlList) {
                        if (temp.getUrlType() != null && temp.getUrlType().intValue() == 2) {
                            recObj = temp;
                            break;
                        }
                    }
                }

                if (recObj == null) {
                    if (branchId != null) {
                        for (ShopBaiduUrlCur temp : shopBaiduUrlList) {
                            if (temp.getUrlType() != null && temp.getUrlType().intValue() == 2) {
                                recObj = temp;
                                break;
                            }
                        }
                    }

                    if (recObj == null) {
                        return "";
                    }
                }

                String token = getAuth(recObj.getApiKey(), recObj.getSecurityKey());

                token = URLEncoder.encode(token);

                setKey(tokenKeyCur + shopId + branchId, token, tokenExpireTime - 10000);
                setKey(baiduAppidKeyCur + shopId + branchId, recObj.getAppid(), tokenExpireTime);

                return token;
            } else {
                return null;
            }
        } else {
            return tokenObj.toString();
        }

    }

    public List<Map<String, String>> getBaiduTokenCurList(Integer shopId, Integer branchId) {
        Condition condition = new Condition(ShopBaiduUrlCur.class);
        condition.or().andEqualTo("shopId", shopId)
                    .andEqualTo("urlType", 2);
        List<ShopBaiduUrlCur> shopBaiduUrlList = shopBaiduUrlCurMapper.selectByCondition(condition);
        if (shopBaiduUrlList != null && shopBaiduUrlList.size() > 0) {
            if (branchId == null) {
                Condition branchCondition = new Condition(Branch.class);
                branchCondition.or().andEqualTo("shopId", shopId);

                List<Branch> branchList = branchMapper.selectByCondition(branchCondition);
                if (branchList != null && branchList.size() == 1) {
                    branchId = branchList.get(0).getBranchId();
                }
            }
            List<ShopBaiduUrlCur> shopBaiduUrlCurList = new ArrayList<>();

            if (branchId != null) {
                for (ShopBaiduUrlCur temp : shopBaiduUrlList) {
                    if (branchId.equals(temp.getBranchId())
                            ) {
                        shopBaiduUrlCurList.add(temp);
                    }
                }
            }else {
                for (ShopBaiduUrlCur temp : shopBaiduUrlList) {
                    shopBaiduUrlCurList.add(temp);
                }
            }

            if (shopBaiduUrlCurList.size() > 0) {
                List<Map<String, String>> mapList = new ArrayList<>();

                for (ShopBaiduUrlCur shopBaiduUrlCur : shopBaiduUrlCurList) {
                    Object token = getKey(tokenKeyCur + shopId + branchId + shopBaiduUrlCur.getAppid());
                    if (token == null) {
                        token = getAuth(shopBaiduUrlCur.getApiKey(), shopBaiduUrlCur.getSecurityKey());
                        token = URLEncoder.encode((String)token);
                        setKey(tokenKeyCur + shopId + branchId + shopBaiduUrlCur.getAppid(),
                                token.toString(), tokenExpireTime - 10000);
                        setKey(baiduAppidKeyCur + shopId + branchId + shopBaiduUrlCur.getAppid(),
                                shopBaiduUrlCur.getAppid(), tokenExpireTime);
                    }

                    Map<String, String> map = new HashMap<>();
                    map.put("token", (String)token);
                    map.put("appid", shopBaiduUrlCur.getAppid());

                    mapList.add(map);
                }

                return mapList;
            }

            return null;
        } else {
            return null;
        }

    }


    public String getBaiduToken(Integer shopId, Integer branchId) {
        Object tokenObj = getKey(tokenKey + shopId + branchId);

        if (tokenObj == null) {
            Condition condition = new Condition(ShopBaiduUrl.class);
            condition.or().andEqualTo("shopId", shopId);
            List<ShopBaiduUrl> shopBaiduUrlList = shopBaiduUrlMapper.selectByCondition(condition);
            if (shopBaiduUrlList != null && shopBaiduUrlList.size() > 0) {
                ShopBaiduUrl recObj = null;

                if (branchId != null) {
                    for (ShopBaiduUrl temp : shopBaiduUrlList) {
                        if (temp.getUrlType() != null && temp.getUrlType().intValue() == 2
                                && branchId.equals(temp.getBranchId())
                                ) {
                            recObj = temp;
                            break;
                        }
                    }
                }else {
                    for (ShopBaiduUrl temp : shopBaiduUrlList) {
                        if (temp.getUrlType() != null && temp.getUrlType().intValue() == 2) {
                            recObj = temp;
                            break;
                        }
                    }
                }

                if (recObj == null) {
                    if (branchId != null) {
                        for (ShopBaiduUrl temp : shopBaiduUrlList) {
                            if (temp.getUrlType() != null && temp.getUrlType().intValue() == 2) {
                                recObj = temp;
                                break;
                            }
                        }
                    }

                    if (recObj == null) {
                        return "";
                    }
                }

                String token = getAuth(recObj.getApiKey(), recObj.getSecurityKey());

                token = URLEncoder.encode(token);

                setKey(tokenKey + shopId + branchId, token, tokenExpireTime - 10000);
                setKey(baiduAppidKey + shopId + branchId, recObj.getAppid(), tokenExpireTime);

                return token;
            } else {
                return null;
            }
        } else {
            return tokenObj.toString();
        }

    }

    /*public String getBaiduToken(Integer shopId, Integer branchId){
        Object tokenObj = getKey(tokenKey + shopId + branchId);

        if (tokenObj == null) {
            Condition condition = new Condition(ShopBaiduUrl.class);
            if (branchId != null) {
                condition.or().andEqualTo("shopId", shopId)
                            .andEqualTo("branchId", branchId)
                ;
            }else {
                condition.or().andEqualTo("shopId", shopId);
            }
            List<ShopBaiduUrl> shopBaiduUrlList = shopBaiduUrlMapper.selectByCondition(condition);
            if (shopBaiduUrlList != null && shopBaiduUrlList.size() > 0) {
                ShopBaiduUrl recObj = null;

                for (ShopBaiduUrl temp : shopBaiduUrlList) {
                    if (temp.getUrlType() != null && temp.getUrlType().intValue() == 2) {
                        recObj = temp;
                        break;
                    }
                }

                if (recObj == null) {
                    recObj = shopBaiduUrlList.get(0);
                }

                String token = getAuth(recObj.getApiKey(), recObj.getSecurityKey());

                token = URLEncoder.encode(token);

                setKey(tokenKey + shopId + branchId, token, tokenExpireTime - 6000);
                setKey(baiduAppidKey + shopId + branchId, recObj.getAppid(), tokenExpireTime);

                return token;
            } else {
                return null;
            }
        }else {
            return tokenObj.toString();
        }

    }*/


    public String addImg(Integer shopId, Integer branchId, String filename, String tag) throws Exception{

        String token = getBaiduToken(shopId, branchId);

        String url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/realtime_search/dish/add?access_token=" + token;

        HttpHeaders DEFAULT_JSON_HEADER = new HttpHeaders();
        MediaType jsontype = MediaType.APPLICATION_FORM_URLENCODED;
        DEFAULT_JSON_HEADER.setContentType(jsontype);


        String filePath = filename;
        byte[] imgData = FileUtil.read(filePath);
        String imgStr = Base64Util.encode(imgData);
        String imgParam = URLEncoder.encode(imgStr, "UTF-8");

        String param = "image=" + imgParam + "&sub_lib=" + getKey(baiduAppidKey + shopId + branchId) + "&brief=" + tag;

        try {
            HttpEntity<String> entity = new HttpEntity<>(param, DEFAULT_JSON_HEADER);

            ResponseEntity<String> result = new RestTemplate().postForEntity(url, entity, String.class);

            System.out.println(result.getBody());
            /**
             * {"log_id": 379096853819015407, "cont_sign": "2743144346,4232638351"}
             */

            Map<String, String> m = JsonUtil.parse(result.getBody(), Map.class);

            if (StringUtils.hasText((String)m.get("cont_sign"))) {
                return (String)m.get("cont_sign");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public String addImgCur(Integer shopId, Integer branchId, String filename, String tag) throws Exception{

        String token = getBaiduTokenCur(shopId, branchId);

        String url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/realtime_search/dish/add?access_token=" + token;

        HttpHeaders DEFAULT_JSON_HEADER = new HttpHeaders();
        MediaType jsontype = MediaType.APPLICATION_FORM_URLENCODED;
        DEFAULT_JSON_HEADER.setContentType(jsontype);


        String filePath = filename;
        byte[] imgData = FileUtil.read(filePath);
        String imgStr = Base64Util.encode(imgData);
        String imgParam = URLEncoder.encode(imgStr, "UTF-8");

        String param = "image=" + imgParam + "&sub_lib=" + getKey(baiduAppidKeyCur + shopId + branchId) + "&brief=" + tag;

        try {
            HttpEntity<String> entity = new HttpEntity<>(param, DEFAULT_JSON_HEADER);

            ResponseEntity<String> result = new RestTemplate().postForEntity(url, entity, String.class);

            System.out.println(result.getBody());
            /**
             * {"log_id": 379096853819015407, "cont_sign": "2743144346,4232638351"}
             */

            Map<String, String> m = JsonUtil.parse(result.getBody(), Map.class);

            if (StringUtils.hasText((String)m.get("cont_sign"))) {
                return (String)m.get("cont_sign");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public List<Map<String, String>> addImgCurList(Integer shopId, Integer branchId, String filename, String tag) throws Exception{

        List<Map<String, String>> tokenList = getBaiduTokenCurList(shopId, branchId);

        if (tokenList != null) {
            List<Map<String, String>> resultList = new ArrayList<>();
            for (Map<String, String> map : tokenList) {
                String token = map.get("token");
                String appid = map.get("appid");
                String url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/realtime_search/dish/add?access_token=" + token;

                HttpHeaders DEFAULT_JSON_HEADER = new HttpHeaders();
                MediaType jsontype = MediaType.APPLICATION_FORM_URLENCODED;
                DEFAULT_JSON_HEADER.setContentType(jsontype);


                String filePath = filename;
                byte[] imgData = FileUtil.read(filePath);
                String imgStr = Base64Util.encode(imgData);
                String imgParam = URLEncoder.encode(imgStr, "UTF-8");

                String param = "image=" + imgParam + "&sub_lib=" + appid + "&brief=" + tag;

                try {
                    HttpEntity<String> entity = new HttpEntity<>(param, DEFAULT_JSON_HEADER);

                    ResponseEntity<String> result = new RestTemplate().postForEntity(url, entity, String.class);

                    System.out.println(result.getBody());
                    /**
                     * {"log_id": 379096853819015407, "cont_sign": "2743144346,4232638351"}
                     */

                    Map<String, String> m = JsonUtil.parse(result.getBody(), Map.class);

                    if (StringUtils.hasText(m.get("cont_sign"))) {

                        String contSign = m.get("cont_sign");

                        Map<String, String> resultMap = new HashMap<>();
                        resultMap.put("appid", appid);
                        resultMap.put("contSign", contSign);

                        resultList.add(resultMap);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            return resultList;
        }


        return null;
    }

    public boolean delImg(String cont_sign, Integer shopId, Integer branchId) {

        String token = getBaiduToken(shopId, branchId);

        String url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/realtime_search/dish/delete?access_token=" + token;

        HttpHeaders DEFAULT_JSON_HEADER = new HttpHeaders();
        MediaType jsontype = MediaType.APPLICATION_FORM_URLENCODED;
        DEFAULT_JSON_HEADER.setContentType(jsontype);


        String param = "cont_sign=" + cont_sign + "&sub_lib=" + getKey(baiduAppidKey + shopId + branchId);

        try {
            HttpEntity<String> entity = new HttpEntity<>(param, DEFAULT_JSON_HEADER);

            ResponseEntity<String> result = new RestTemplate().postForEntity(url, entity, String.class);

            logger.info(result.getBody());
            /**
             * {"log_id": 379096853819015407, "cont_sign": "2743144346,4232638351"}
             */

            Map<String, Object> m = JsonUtil.parse(result.getBody(), Map.class);

            if (m.get("log_id") != null && !m.containsKey("error_code")) {
                return true;
            }
            if (m.containsKey("error_code")) {
                Integer errorCode = (Integer) m.get("error_code");
                if (errorCode.equals(216680)) {
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }



    public boolean delImgCur(String cont_sign, Integer shopId, Integer branchId) {

        String token = getBaiduTokenCur(shopId, branchId);

        String url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/realtime_search/dish/delete?access_token=" + token;


        String param = "cont_sign=" + cont_sign + "&sub_lib=" + getKey(baiduAppidKeyCur + shopId);

        try {
            HttpHeaders DEFAULT_JSON_HEADER = new HttpHeaders();
            MediaType jsontype = MediaType.APPLICATION_FORM_URLENCODED;
            DEFAULT_JSON_HEADER.setContentType(jsontype);

            HttpEntity<String> entity = new HttpEntity<>(param, DEFAULT_JSON_HEADER);

            ResponseEntity<String> result = new RestTemplate().postForEntity(url, entity, String.class);

            logger.info(result.getBody());
            /**
             * {"log_id": 379096853819015407, "cont_sign": "2743144346,4232638351"}
             */

            Map<String, Object> m = JsonUtil.parse(result.getBody(), Map.class);

            if (m.get("log_id") != null && !m.containsKey("error_code")) {
                return true;
            }
            if (m.containsKey("error_code")) {
                Integer errorCode = (Integer) m.get("error_code");
                if (errorCode.equals(216680)) {
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    public boolean delImgCurList(String cont_sign, Integer shopId, Integer branchId, String appid) {

        List<Map<String, String>> tokenList = getBaiduTokenCurList(shopId, branchId);

        if (tokenList != null) {
            for (Map<String, String> map : tokenList) {
                String token = map.get("token");
                String dbappid = map.get("appid");

                if (StringUtils.isEmpty(appid)) {
                    appid = dbappid;
                }
                if (dbappid.equals(appid)) {
                    String url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/realtime_search/dish/delete?access_token=" + token;


                    String param = "cont_sign=" + cont_sign + "&sub_lib=" + dbappid;

                    try {
                        HttpHeaders DEFAULT_JSON_HEADER = new HttpHeaders();
                        MediaType jsontype = MediaType.APPLICATION_FORM_URLENCODED;
                        DEFAULT_JSON_HEADER.setContentType(jsontype);

                        HttpEntity<String> entity = new HttpEntity<>(param, DEFAULT_JSON_HEADER);

                        ResponseEntity<String> result = new RestTemplate().postForEntity(url, entity, String.class);

                        logger.info(result.getBody());
                        /**
                         * {"log_id": 379096853819015407, "cont_sign": "2743144346,4232638351"}
                         */

                        Map<String, Object> m = JsonUtil.parse(result.getBody(), Map.class);

                        if (m.get("log_id") != null && !m.containsKey("error_code")) {
                            return true;
                        }
                        if (m.containsKey("error_code")) {
                            Integer errorCode = (Integer) m.get("error_code");
                            if (errorCode.equals(216680)) {
                                return true;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }



        return false;
    }


    /**
     * 获取API访问token
     * 该token有一定的有效期，需要自行管理，当失效时需重新获取.
     * @param ak - 百度云官网获取的 API Key
     * @param sk - 百度云官网获取的 Securet Key
     * @return assess_token 示例：
     * "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"
     */
    public static String getAuth(String ak, String sk) {
        // 获取token地址
        String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
        String getAccessTokenUrl = authHost
                // 1. grant_type为固定参数
                + "grant_type=client_credentials"
                // 2. 官网获取的 API Key
                + "&client_id=" + ak
                // 3. 官网获取的 Secret Key
                + "&client_secret=" + sk;
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.err.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            /**
             * 返回结果示例
             */
            System.err.println("result:" + result);
            JSONObject jsonObject = new JSONObject(result);
            String access_token = jsonObject.getString("access_token");
            tokenExpireTime = jsonObject.getLong("expires_in");
            return access_token;
        } catch (Exception e) {
            System.err.printf("获取token失败！");
            e.printStackTrace(System.err);
        }
        return null;
    }

}
